package com.stary.springmvc.web.requestparam;

import com.stary.springmvc.web.requestparam.pojo.Master;
import com.stary.springmvc.web.requestparam.pojo.Pet;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Map;

@Controller
@RequestMapping(value = "/vote")
public class VoteHandler {
    /**
     * 解读：
     *  1.获取超链接传输的数据  请求url：http://localhost:8080/springmvc/vote/vote01?name=stary
     *  2.@RequestParam 注解用于接收请求传进来的参数，注解提供功能-参数不必与前端参数名一致
     *  3.value = "name"：表示提交的参数名是name
     *  4.required = false：表示这个参数可以有也可以没有。默认值是true，即必须有这个参数
     *  5.当我们使用了.@RequestParam后，请求的参数名和方法的实参可以不一致
     */
    @RequestMapping(value = "/vote01")
    public String testRequestParameter(@RequestParam(value = "name",required = false) String username){
        System.out.println("username = " + username);
        return "success";
    }

    /**
     * 需求：获取请求头信息：Accept-Encoding和Host
     * RequestHeader("Http请求头字段")
     * RequestHeader("Accept-Encoding")：想要获取的信息
     */
    @RequestMapping("/vote02")
    public String getRequestHeader(@RequestHeader("Accept-Encoding") String ae,
                                   @RequestHeader("Host") String host){
        System.out.println("ae = " + ae);
        System.out.println("host = " + host);
        return "success";
    }


    /**
     * 将获取到的数据封装成对象
     *  解读：
     *   1.方法的形参用对应的类型来指定即可，SpringMVC会自动进行封装
     *   2.如果是自动完成封装，则需要提交的数据-参数名与对象的字段名保持一致
     *   3.如果属性是对象，我们通过字段名.字段名的方式提交数据
     *     例如Master[pet]，提交的数据名应该是 pet.id,pet.name等等【级联操作】
     *   4.如果提交数据的参数名和对象的字段名不匹配，则对象的属性值为null
     */
    @RequestMapping("/vote03")
    public String getPojoObject(Master master){
        System.out.println("master = " + master);
        return "success";

    }


    /**
     * 原生Servlet-api的使用
     */
    @RequestMapping("/vote04")
    public String servletApiTest(HttpServletRequest req, HttpServletResponse resp,HttpSession hs){
        String username = req.getParameter("username");
        System.out.println("username = " + username);
        String pwd = req.getParameter("pwd");
        System.out.println("pwd = " + pwd);

        //我们可以发现，这俩个session是相同的
        HttpSession session = req.getSession();
        System.out.println("session = " + session);
        System.out.println("hs = " + hs);
        System.out.println(hs == session);
        return "success";
    }

    /**
     *  需求：前端提交数据 -- 后端接收数据，并放入request域中 -- 在跳转到的其他页面取出数据
     *  解读：
     *   1.提交过来的数据->springMVC将其封装成java对象->springMVC会自动的将其放入request域中
     *   2.在request域中存储的方式 ("master",master)--->(名字,对象)
     *     springmvc默认存放对象到request的属性名是类名的首字母小写
     *  注意：jsp文件可能会出现el表示失败问题
     *  解决方案：加入<%@page isELIgnored="false" %>
     */
    @RequestMapping("/vote05")
    public String testRequestArea(Master master,HttpServletRequest req){

        //解读：
        //1，springmvc会自动获取的model模型，放入到request域中，名字就是master
        //2.我们可以手动的将数据放入master[利用HttpServletRequest ]
        Pet pet = new Pet(1,"小猫");
        req.setAttribute("pet1",pet);
        //3.我们可以修改master的属性值
        master.setName("aa");
        return "voke_ok";
    }

    /**
     *  需求：演示通过Map<String,Object> 设置数据到request域中
     */
    @RequestMapping(value = "/vote06")
    public String testMapRequest(Master master, Map<String,Object> map){
        //解读：
        //springmvc会遍历map，然后将mao的k-v放入到请求域中
        map.put("address","shenyang");
        //注意：如果一个属性名重复出现，则覆盖
//        map.put("master",null);
        return "voke_ok";
    }

    /**
     *  1.需求：演示返回ModelAndView对象，将数据放入request域
     *  2.简单理解
     *    Model：数据
     *    View：要返回到的页面
     *  3.机制与map相似
     */
    @RequestMapping("/vote07")
    public ModelAndView test02(Master master){
        ModelAndView modelAndView = new ModelAndView();
        //放入属性到ModelAndView对象——实际中我们从数据库中得到数据->封装对象->放入到ModelAndView
        modelAndView.addObject("address","shenzhen");
        //指定跳转的视图名称
        modelAndView.setViewName("voke_ok");
        //返回结果
        return modelAndView;
    }

    /**
     *  需求：演示将数据放到session域中
     *  问：为什么request域中的数据也显示了呢？
     *  答：封装的对象默认放到了request域中
     */
    @RequestMapping("/vote08")
    public String testSessionScope(Master master,HttpSession session){
        session.setAttribute("master",master);
        session.setAttribute("address","shanghai");
        return "voke_ok";
    }

    /**
     *  前置方法
     *  解读：
     *   1.当Handler的方法被@ModelAttribute注解标识，该方法就视为一个前置方法
     *   2.当调用Handler的其他方法时，都会先执行该前置方法
     *   3.底层是aop机制
     *   4.用处
     */
    @ModelAttribute
    public void  prepareModel(){
        System.out.println("前置方法被调用");
    }
}
